package se.grp03.fmtuner.scheduler;

import java.text.ParseException;
import java.util.Date;

import org.quartz.JobDataMap;
import org.quartz.ObjectAlreadyExistsException;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.impl.JobDetailImpl;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.quartz.impl.triggers.SimpleTriggerImpl;

import se.grp03.fmtuner.scheduler.io.IOInterface;
import se.grp03.fmtuner.scheduler.io.StdioAdapter;
import se.grp03.fmtuner.scheduler.io.UdpAdapter;
import se.grp03.fmtuner.scheduler.io.UdpConstants;
import se.grp03.fmtuner.scheduler.job.HourlyScanJob;
import se.grp03.fmtuner.scheduler.job.TuneJob;

public class SchedulerManager {

	private static SchedulerManager sm; // Singleton
	private static Scheduler scheduler;
	//private static IOInterface io;
	
	private SchedulerManager() {}

	public static SchedulerManager getInstance() {            
		if(sm == null)
			sm = new SchedulerManager();
		return sm;
	}

	/**
	 * Initializes and starts the Quartz Scheduler.
	 * @param debug - True if using STDIO instead of UDP communications.
	 * @throws SchedulerException
	 */
	public void startScheduler(boolean debug) throws SchedulerException {
    	scheduler = new StdSchedulerFactory().getScheduler();
    	//scheduler.getListenerManager().addJobListener(new SchedulerListener());
    	scheduler.start();
    	
    	/*if(debug) // If true, uses STDIO instead of UDP.
    		io = new StdioAdapter(UdpConstants.AGENT_PORT);
    	else
    		io = new UdpAdapter(UdpConstants.AGENT_PORT);
    	io.doOpen();*/
	}

	/**
	 * Schedules an hourly job with the Quartz Scheduler, which sends 
	 * a scan message to the FM Tuner Agent.
	 * @throws ParseException
	 */
	public void scheduleHourlyScanJob() throws ParseException {		
		// Set hourly scan job details.
		JobDetailImpl job = new JobDetailImpl();
		job.setJobClass(HourlyScanJob.class);
		job.setName("HourlyScanJob");
		
		// Pass values to scan job.
		JobDataMap jdm = new JobDataMap();
		//jdm.put("IO_INTERFACE", io);
		jdm.put("SCAN_MESSAGE", UdpConstants.SCAN);
		job.setJobDataMap(jdm);
    	
        // Set hourly scan trigger details.
        CronTriggerImpl trigger = new CronTriggerImpl();
    	trigger.setName("hourlyScanTrigger");
    	//trigger.setCronExpression("0/10 * * * * ?");	// Every 10 seconds.
    	trigger.setCronExpression("0 0 0/1 * * ?");	// Every hour, on the hour.
    	
    	// Schedule job.
    	try {
			scheduler.scheduleJob(job, trigger);
			System.out.println("Hourly scan job scheduled.");
		} 
    	catch (ObjectAlreadyExistsException e) {
    		System.err.println("** ERROR: Hourly scan job already scheduled!");
    	}
    	catch (SchedulerException e) { System.err.println(e); }
	}

	/**
	 * Schedules a scan job with the Quartz Scheduler, at a specific
	 * time, which sends a tune message to the FM Tuner Agent.
	 * @param frequency - The FM radio frequency.
	 * @param time - The time to schedule the event.
	 */
	public void scheduleTuneJob(String frequency, Date time) {		
		JobDetailImpl job = new JobDetailImpl();
		job.setJobClass(TuneJob.class);
		job.setName("TuneJob." + time);		
		
		// Pass values to tune job.
		JobDataMap jdm = new JobDataMap();
		//jdm.put("IO_INTERFACE", io);
		jdm.put("TUNE_MESSAGE", frequency);
		job.setJobDataMap(jdm);
		
        // Set hourly scan trigger details.
		SimpleTriggerImpl trigger = new SimpleTriggerImpl();
    	trigger.setName("TuneTrigger." + time);
    	trigger.setStartTime(time);
    	
    	// Schedule job.
    	try {
			scheduler.scheduleJob(job, trigger);
		} catch (SchedulerException e) {
			e.printStackTrace();
		}
	}
}